package com.atguigu.demojuc.chap02;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 锁降级：
 *      当前线程拥有了写锁，获取读锁，释放写锁的过程，称为锁降级。
 *      先获取读锁，再释放写锁
 *      好处：
 *          提高并发读的效率。
 *              写锁换成读锁后，可以并发读
 *
 */
public class LockDowngradingDemo {
    //源码：
    /*public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new ReentrantReadWriteLock.FairSync() : new ReentrantReadWriteLock.NonfairSync();
        readerLock = new ReentrantReadWriteLock.ReadLock(this);
        writerLock = new ReentrantReadWriteLock.WriteLock(this);
    }*/

    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); //默认非公平锁false。  如果设置为true表示公平锁。
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    private int data = 0;

    //读锁具有可重入性
    public int readData() {
        readLock.lock();
        //readLock.lock();
        try {
            return data;
        } finally {
            readLock.unlock();
            //readLock.unlock();
        }
    }

    //写锁具有可重入性
    public void updateData(int newData) {
        writeLock.lock();
        //writeLock.lock();
        try {
            data = newData; // 更新数据
            System.out.println("Data updated to: " + newData);

            // 锁降级  :  只支持锁降级，但不支持锁升级。
            readLock.lock(); // 获取读锁
            System.out.println("Lock downgraded to read lock.");
        } finally {
            writeLock.unlock(); // 释放写锁
            //writeLock.unlock(); // 释放写锁
        }

        try {
            // 在持有读锁的情况下执行其他操作
            int currentData = readData();
            System.out.println("Read data: " + currentData);
        } finally {
            readLock.unlock(); // 释放读锁
        }
    }

    /**
     *
     * @param args
     */
    public static void main(String[] args) {

        LockDowngradingDemo example = new LockDowngradingDemo();

        new Thread(() -> {
            example.updateData(42);
        }).start();

        new Thread(() -> {
            int currentData = example.readData();
            System.out.println("Reader got data: " + currentData);
        }).start();
    }
}